#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string>
#include <cstdlib>
#include <errno.h>
#include <cstring>
#include <stdio.h>
#include <vector>
#include <stdlib.h>
using namespace std;

#define NUM 5

// void *threadsun(void *name)
// {
//     char *str = (char*)name;
//     int cnt=3;
//     while (cnt--)
//     {
//         sleep(1);
//         cout << str << endl;
//     }

//     delete[] str;
//     pthread_exit((void*)"exit");
// }

// int main()
// {
//     pthread_t thread[NUM];

//     for (int i = 1; i <= NUM; i++)
//     {
//         char* buffer= new char[64];//new 动态初始化
//         snprintf(buffer,64,"我是thread-%d号", i);//sizeof的用法
//         pthread_create(&thread[i-1], nullptr, threadsun, buffer);
//     }

//     // int cnt=4;
//     // while (cnt--)
//     // {
//     //     sleep(1);
//     //     cout << "我是主线程，我最牛逼" << endl;
//     // }

//     for (int i = 1; i <= NUM; i++)
//     {
//         // pthread_cancel(thread[i-1]);
        
//         void* ret;
//         int n=pthread_join(thread[i-1],&ret);
//         // if(n==-1) printf("我错了\n");
//         cout<<(int64_t)ret<<strerror(n)<<endl;
//         // cout<<"线程thread"<<i<<"退出了 TID"<<thread[i-1]<<(char*)ret<<strerror(n)<<endl;
//     }

//     pthread_exit(0);  
// }
//主线程return 会使所有的线程都退出，detach是不关心线程的退出值，




// class Request
// {
// public:
//     Request(int start,int end,const string& name)
//     :_start(start)
//     ,_end(end)
//     ,threadname(name)
//     {}
// public:
//     int _start;
//     int _end;
//     string threadname;
// };

// class Response
// {
// public:
//     Response(int result,int exitcode)
//     :_result(result)
//     ,_exitcode(exitcode)
//     {}
// public:
//     int _result;
//     int _exitcode;
// };

// void* sumCount(void*args)
// {
//     Request* rq=static_cast<Request*>(args);
    
//     Response* rep=new Response(0,0);

//     for(int i=rq->_start;i<=rq->_end;i++)
//     {
//         rep->_result+=i;
//     }
//     sleep(5);
//     return rep;
// }

// int main()
// {
//     pthread_t tid;
//     Request* rs=new Request(1,100,"thread 1");
//     pthread_create(&tid,nullptr,sumCount,rs);
    
//     sleep(3);
//     pthread_cancel(tid);
//     void *ret;
//     pthread_join(tid,&ret);
//     // cout<<(int64_t)ret<<endl;
//     // Response* rsp=static_cast<Response*>(ret);
//     // cout<<"thread return"<<tid<<rsp->_result<<pthread_self()<<endl;
//     return 0;
// }
// #include <iostream>
// #include <pthread.h>
// #include <unistd.h>
// #include <errno.h>
// #include <cstring>

// using namespace std;

// void* thread_func(void* arg)
// {
//     cout << "Thread started!" << endl;
//     sleep(2); 
//     cout << "Thread finished!" << endl;
//     return nullptr;
// }

// int main()
// {
//     pthread_t tid;

//     pthread_create(&tid, nullptr, thread_func, nullptr);

//     pthread_detach(tid);
//     cout << "Thread detached!" << endl;

//     void* ret;
//     int res = pthread_join(tid, &ret);
//     if (res != 0)
//     {
//         cout << "pthread_join failed. Reason: " << strerror(res) << endl;
//     }

//     return 0;
// }

// pthread_mutex_t mxt=PTHREAD_MUTEX_INITIALIZER;


// __thread int tickets=1;

// class threadData
// {
// public:
//     threadData(int i)
//     {
//         threadname="thread -"+to_string(i);
//     }
//     string threadname;
// };

// void* getticket(void* args)
// {
//     threadData *data=static_cast<threadData*>(args);
//     const char*name=data->threadname.c_str();
//     while(1)
//     {
//         // pthread_mutex_lock(&mxt);
//         if(tickets>0)
//         {
//             usleep(1000);
//             tickets--;
//             printf("%s,获得一张票，还剩%d\n",name,tickets);
//         // pthread_mutex_unlock(&mxt);
//         }
//         else
//         {
//         // pthread_mutex_unlock(&mxt);
//             break;
//         }
//     }

//     printf("quit %s",name);

//     pthread_exit(nullptr);
// }

// int main()
// {
//     vector<pthread_t> tids;
//     vector<threadData *> data;

//     for(int i=1;i<=NUM;i++)
//     {
//         pthread_t p;
//         threadData* t=new threadData(i);
//         pthread_create(&p,nullptr,getticket,t);
//         data.push_back(t);
//         tids.push_back(p);
//     } 

//     for(auto i:tids)
//     {
//         pthread_join(i,nullptr);
//     }

//     for(auto i:data)
//     {
//         delete i;
//     }

//     return 0;
// }


int cnt = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *Count(void * args)
{
    printf("%p\n",args);
    pthread_detach(pthread_self());
    uint64_t number = (uint64_t)args;
    std::cout << "pthread: " << number << " create success" << std::endl;

    while(true)
    {
        pthread_mutex_lock(&mutex);
        // 我们怎么知道我们要让一个线程去休眠了那？一定是临界资源不就绪，没错，临界资源也是有状态的！！
        // 你怎么知道临界资源是就绪还是不就绪的？你判断出来的！判断是访问临界资源吗？必须是的，也就是判断必须在加锁之后！！！
        pthread_cond_wait(&cond, &mutex);               //？ 为什么在这里？ 1. pthread_cond_wait让线程等待的时候，会自动释放锁！
        // 不管临界资源的状态情况
        std::cout << "pthread: " << number << " ， cnt: " << cnt++ << std::endl;
        pthread_mutex_unlock(&mutex);
    }
}

int main()
{
    for(uint64_t i = 0; i < 5; i++)
    {
        pthread_t tid;
        pthread_create(&tid, nullptr, Count, (void*)i);
        usleep(1000);
    }
    sleep(3);
    std::cout << "main thread ctrl begin: " << std::endl;

    while(true) 
    {
        sleep(1);
        // pthread_cond_signal(&cond); //唤醒在cond的等待队列中等待的一个线程，默认都是第一个
        pthread_cond_broadcast(&cond);
        std::cout << "signal one thread..." << std::endl;
    }

    return 0;
}